package com.mutouren.common.orm;

import java.util.List;
import java.util.Map;

import org.apache.ibatis.session.SqlSession;

/**
 * Ibatis助手
 * 功能:
 * 1. 对数据操作
 * 2. 对事务管理统一管理
 * 3. 通过cfgName (即：Mybatis配置文件中environment-id)，区分不同数据源
 * 4. 提供接口方法，跟原生mybatis类库保持一致。
 * 5. 稍后，支持主-从库统一管理
 * 
 */
public class IbatisHelper {

//	private static <T> T executeWithNewSession(IbatisCallback<T> action) {
//		IbatisTrans trans = new IbatisTrans();
//		try{
//			trans.begin();
//			T result = action.doInIbatis(trans.getSession());			
//						
//			trans.commit();
//			return result;
//		} catch(RuntimeException ex) {
//			trans.rollback();
//			throw ex;
//		} finally {
//			trans.close();
//		}
//	}
	
	private static <T> T execute(IbatisCallback<T> action, IbatisTrans trans) {
//		if(trans == null) {
//			return executeWithNewSession(action);
//		} else {			
//			return action.doInIbatis(trans.getSession());
//		}
		return action.doInIbatis(trans.getSession());
	}
	
	private static <T> T execute(IbatisCallback<T> action, String cfgName) {
		IbatisTrans trans = new IbatisTrans(cfgName);
		try{
			trans.begin();
			T result = action.doInIbatis(trans.getSession());			
						
			trans.commit();
			return result;
		} catch(RuntimeException ex) {
			trans.rollback();
			throw ex;
		} finally {
			trans.close();
		}
	}
	
	public static <T> T selectOne(final String statement, final Object parameter, String cfgName) {
		return execute(new IbatisCallback<T>() {
			@Override
			public T doInIbatis(SqlSession session) {
				return session.selectOne(statement, parameter);		
			}
		}, cfgName);
	}
	public static <T> T selectOne(final String statement, final Object parameter, IbatisTrans trans) {
		return execute(new IbatisCallback<T>() {
			@Override
			public T doInIbatis(SqlSession session) {
				return session.selectOne(statement, parameter);		
			}
		}, trans);
	}
	
	public static <T> List<T> selectList(final String statement, final Object parameter, String cfgName) {
		return execute(new IbatisCallback<List<T>>() {
			@Override
			public List<T> doInIbatis(SqlSession session) {
				return session.selectList(statement, parameter);		
			}
		}, cfgName);
	}
	public static <T> List<T> selectList(final String statement, final Object parameter, IbatisTrans trans) {
		return execute(new IbatisCallback<List<T>>() {
			@Override
			public List<T> doInIbatis(SqlSession session) {
				return session.selectList(statement, parameter);		
			}
		}, trans);
	}
	
	public static <K,V> Map<K,V> selectMap(final String statement, final Object parameter, final String mapKey, String cfgName) {
		return execute(new IbatisCallback<Map<K,V>>() {
			@Override
			public Map<K,V> doInIbatis(SqlSession session) {
				return session.selectMap(statement, parameter, mapKey);
				//return session.selectList(statement, parameter);		
			}
		}, cfgName);
	}
	public static <K,V> Map<K,V> selectMap(final String statement, final Object parameter, final String mapKey, IbatisTrans trans) {
		return execute(new IbatisCallback<Map<K,V>>() {
			@Override
			public Map<K,V> doInIbatis(SqlSession session) {
				return session.selectMap(statement, parameter, mapKey);		
			}
		}, trans);
	}	
	
	public static void insert(final String statement, final Object parameter, String cfgName) {
		execute(new IbatisCallback<Object>() {
			@Override
			public Object doInIbatis(SqlSession session) {
				int result = session.insert(statement, parameter);
				if(result == 0) {
					throw new RuntimeException("Ibatis insert fail, statement: " + statement);
				}
				return null;				
			}
		}, cfgName);
	}
	public static void insert(final String statement, final Object parameter, IbatisTrans trans) {
		execute(new IbatisCallback<Object>() {
			@Override
			public Object doInIbatis(SqlSession session) {
				int result = session.insert(statement, parameter);
				if(result == 0) {
					throw new RuntimeException("Ibatis insert fail, statement: " + statement);
				}
				return null;				
			}
		}, trans);
	}
	
	public static int update(final String statement, final Object parameter, String cfgName) {
		return execute(new IbatisCallback<Integer>() {
			@Override
			public Integer doInIbatis(SqlSession session) {
				return session.update(statement, parameter);				
			}
		}, cfgName);
	}
	public static int update(final String statement, final Object parameter, IbatisTrans trans) {
		return execute(new IbatisCallback<Integer>() {
			@Override
			public Integer doInIbatis(SqlSession session) {
				return session.update(statement, parameter);				
			}
		}, trans);
	}
	
	public static int delete(final String statement, final Object parameter, String cfgName) {
		return execute(new IbatisCallback<Integer>() {
			@Override
			public Integer doInIbatis(SqlSession session) {
				return session.delete(statement, parameter);
			}
		}, cfgName);
	}
	public static int delete(final String statement, final Object parameter, IbatisTrans trans) {
		return execute(new IbatisCallback<Integer>() {
			@Override
			public Integer doInIbatis(SqlSession session) {
				return session.delete(statement, parameter);
			}
		}, trans);
	}
		
}
